/**
 * Copyright (c) 2010-2020 by skzr.org
 * All rights reserved.
 * @Author skzr.org(E-mail:skzr.org@gmail.com)
 * @date 2010-4-26 下午06:04:50
 */
package org.skzr.proxy;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.entity.AbstractHttpEntity;
import org.skzr.framework.util.UtilIO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @jdk 1.6
 * @author skzr.org(E-mail:skzr.org@gmail.com)
 * @version 1.0.0
 */
public class ProxyEntity extends AbstractHttpEntity {
	protected final transient Logger logger = LoggerFactory.getLogger(getClass());
	private ByteArrayOutputStream headerStream = new ByteArrayOutputStream(2048);
	private boolean consumed = false;
	private long entitySize = -1;
	private boolean finish = false;
	private String method, url, protocol;
	private Long contentLength;
	private List<String[]> headers = new ArrayList<String[]>();
	private InputStream body;
	
	private boolean isGet() {
		return "GET".equals(method);
	}
	
	private void commitHeaders() {
		if (!finish) {
			finish = true;
			try {
			//method,url,protocol,headers.size(),headers,content
				DataOutputStream dout = new DataOutputStream(headerStream);
				dout.writeUTF(method);
				
				dout.writeUTF(url);
				dout.writeUTF(protocol);
				dout.writeInt(headers.size());
				for (String[] h : headers) {
					dout.writeUTF(h[0]);
					dout.writeUTF(h[1]);
				}
				dout.close();
			} catch (IOException e) {
				logger.warn("封装Header数据失败", e);
				throw new IllegalStateException("封装Header数据失败", e);
			}
			if (isGet()) {
				entitySize = headerStream.size();
			} else {
				if (contentLength != null && contentLength.intValue() > -1) {
					entitySize = headerStream.size() + contentLength.intValue();
				}
			}
		}
	}
	
	private void checkFinish() {
		if (finish) throw new IllegalStateException(this + "已经设定内容大小" + entitySize + "bytes，故不允许添加数据");
	}
	
	public void setBody(InputStream body) {
		this.body = body;
	}
	
	public void setRawUrl(String method, String url, String protocol) {
		checkFinish();
		this.method = method;
		this.url = url;
		this.protocol = protocol;
	}
	
	public void addHeader(String name, String value) {
		checkFinish();
		headers.add(new String[]{name, value});
		if (name.toLowerCase().equals("content-length")) {
			if (contentLength != null) {
				throw new IllegalStateException("[开发者][逻辑错误]" + method + " " + url + " " + protocol + 
						" 存在多个[header]content-length: " + contentLength);
			}
			contentLength = Long.valueOf(value, 10);
		}
	}
	
	@Override
	public InputStream getContent() throws IOException, IllegalStateException {
		IllegalStateException e = new IllegalStateException("未实现代码");
		logger.warn("getContent()", e);
		throw e;
	}

	@Override
	public long getContentLength() {
		commitHeaders();
		logger.debug("getContentLength() == {}", entitySize);
		return entitySize;
	}

	@Override
	public boolean isRepeatable() {
		logger.debug("isRepeatable() == false");
		return false;
	}

	@Override
	public boolean isStreaming() {
		logger.debug("isStreaming() == {}", !this.consumed);
		return !this.consumed;
	}

	@Override
	public void writeTo(OutputStream out) throws IOException {
		logger.trace("writeTo({})", out);
		commitHeaders();
		out.write(headerStream.toByteArray());
		if (!"GET".equals(method) && body != null) {
			UtilIO.write(body, out, contentLength != null ? contentLength : 0);
		}
		UtilIO.close(body);
		logger.trace("writeTo({}) finish", out);
		consumed = true;
	}
	
	@Override
	public void consumeContent() throws IOException, UnsupportedOperationException {
		logger.trace("consumeContent(){consumed = true; close(body);}");
		consumed = true;
		UtilIO.close(body);
	}
}
